home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / sipp / sphigs / src / src.arj / MAT3VEC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-12  |  8.6 KB  |  253 lines

  1. /* Copyright 1991, Brown Computer Graphics Group.  All Rights Reserved. */
  2.  
  3. #ifndef lint
  4. static char Version[] = 
  5.    "$Id: MAT3vec.c,v 1.2 1993/03/09 02:00:54 crb Exp $";
  6. #endif
  7.  
  8. /* -------------------------------------------------------------------------
  9.  *
  10.  *  This file contains routines that operate on matrices and vectors, or
  11.  *  vectors and vectors.
  12.  *  
  13.  * ------------------------------------------------------------------------- */
  14.  
  15. #include "mat3defs.h"
  16. #include <assert.h>
  17.  
  18. /* ------------------------ Static Routines  ------------------------------- */
  19.  
  20.  
  21. /* ------------------------ Private Routines ------------------------------- */
  22.  
  23.  
  24. /* ------------------------ Public Routines  ------------------------------- */
  25. /*LINTLIBRARY*/
  26.  
  27. /* -------------------------------------------------------------------------
  28.  * DESCR :    Multiplies the vector @vec@ by the matrix @mat@, and places
  29.  *         the result in @result_vec@. The routine assumes all
  30.  *         homogeneous coordinates are 1. The two vectors involved may
  31.  *         be the same.
  32.  *
  33.  * RETURNS :    void
  34.  * ------------------------------------------------------------------------- */
  35. void
  36. MAT3mult_vec(
  37.    register MAT3vec result_vec,    /* The product of vec and mat (output) */
  38.    register MAT3vec vec,           /* The vector to be multiplied (input) */
  39.    register MAT3mat mat     /* The matrix it's multiplied by (input)*/
  40.    )
  41. {
  42.    MAT3vec        tempvec;
  43.    register double    *temp = tempvec;
  44.  
  45.    temp[0] =    vec[0] * mat[0][0] + vec[1] * mat[0][1] +
  46.         vec[2] * mat[0][2] +          mat[0][3];
  47.    temp[1] =    vec[0] * mat[1][0] + vec[1] * mat[1][1] +
  48.         vec[2] * mat[1][2] +          mat[1][3];
  49.    temp[2] =    vec[0] * mat[2][0] + vec[1] * mat[2][1] +
  50.         vec[2] * mat[2][2] +          mat[2][3];
  51.  
  52.    MAT3_COPY_VEC(result_vec, temp);
  53. }
  54.  
  55. /* -------------------------------------------------------------------------
  56.  * DESCR :    Multiplies the vector of size 4 (@vec@) by the matrix @mat@,
  57.  *         placing the result in @result_vec@. (The multiplication is of
  58.  *         the form matrix times vector, and the vector should be
  59.  *         considered to be a column vector). The fourth element of the
  60.  *         vector is the homogeneous coordinate, which may or may not be
  61.  *         1.  If the @homogenize@ parameter is TRUE, then the result
  62.  *         vector will be normalized so that the homogeneous coordinate
  63.  *         is 1. The two vectors involved may be the same. This returns
  64.  *         zero if the vector was to be homogenized, but couldn't be.
  65.  *
  66.  *
  67.  * RETURNS :    FALSE if the result vector was to be homogenized, but had
  68.  *         homogeneous coordinate zero. In this case, the results should
  69.  *         be regarded as garbage. Otherwise the routine returns TRUE.
  70.  * ------------------------------------------------------------------------- */
  71. int
  72. MAT3mult_hvec(
  73.    MAT3hvec          result_vec, /* The product of vec with mat (output) */
  74.    register MAT3hvec vec,     /* The vector to multiply (input) */
  75.    register MAT3mat  mat,     /* The matrix to multiply (input) */
  76.    int               homogenize     /* Should we homogenize the result?  */
  77.    )
  78. {
  79.    MAT3hvec             tempvec;
  80.    double        norm_fac;
  81.    register double    *temp = tempvec;
  82.    register int     ret = TRUE;
  83.  
  84.    temp[0] =    vec[0] * mat[0][0] + vec[1] * mat[0][1] +
  85.         vec[2] * mat[0][2] + vec[3] * mat[0][3];
  86.    temp[1] =    vec[0] * mat[1][0] + vec[1] * mat[1][1] +
  87.         vec[2] * mat[1][2] + vec[3] * mat[1][3];
  88.    temp[2] =    vec[0] * mat[2][0] + vec[1] * mat[2][1] +
  89.         vec[2] * mat[2][2] + vec[3] * mat[2][3];
  90.    temp[3] =    vec[0] * mat[3][0] + vec[1] * mat[3][1] +
  91.         vec[2] * mat[3][2] + vec[3] * mat[3][3];
  92.  
  93.    /* Homogenize if asked for, possible, and necessary */
  94.    if (homogenize) {
  95.       if (MAT3_IS_ZERO(temp[3])) {
  96.      SEVERES("Can't homogenize vec. in MAT3mult_hvec: last coord is 0");
  97.      ret = FALSE;
  98.       }
  99.       else {
  100.      norm_fac = 1.0 / temp[3];
  101.      MAT3_SCALE_VEC(result_vec, temp, norm_fac);
  102.      result_vec[3] = 1.0;
  103.       }
  104.    }
  105.    else MAT3_COPY_HVEC(result_vec, temp);
  106.  
  107.    return(ret);
  108. }
  109.  
  110. /* -------------------------------------------------------------------------
  111.  * DESCR   :    Multiply the matrix @mat@ by the vector @vec@ and normalize
  112.  *         the result. The vector @vec@ has no homogeneous component,
  113.  *         and thus the homogeneous component is assumed to be 1. The
  114.  *         resulting vector @result_vec@ is of the same form.
  115.  *
  116.  * RETURNS :    TRUE unless the resulting vector would have had a homogeneous
  117.  *         coordinate of zero, in which case FALSE is returned and the
  118.  *         values in @result_vec@ are meaningless.
  119.  * ------------------------------------------------------------------------- */
  120. int
  121. MAT3mult_vec_affine(
  122.    MAT3vec           result_vec,    /* The computed product (output) */
  123.    register MAT3vec  vec,        /* The vector factor (input) */
  124.    register MAT3mat  mat         /* The matrix factor (input) */
  125.    )
  126. {
  127.    MAT3hvec             tempvec;
  128.    double        norm_fac;
  129.    register double    *temp = tempvec;
  130.    register int     ret = TRUE;
  131.  
  132.    temp[0] =    vec[0] * mat[0][0] + vec[1] * mat[0][1] +
  133.         vec[2] * mat[0][2] +          mat[0][3];
  134.    temp[1] =    vec[0] * mat[1][0] + vec[1] * mat[1][1] +
  135.         vec[2] * mat[1][2] +          mat[1][3];
  136.    temp[2] =    vec[0] * mat[2][0] + vec[1] * mat[2][1] +
  137.         vec[2] * mat[2][2] +          mat[2][3];
  138.    temp[3] =    vec[0] * mat[3][0] + vec[1] * mat[3][1] +
  139.         vec[2] * mat[3][2] +          mat[3][3];
  140.  
  141.    /* Homogenize if possible */
  142.    if (MAT3_IS_ZERO(temp[3])) {
  143.      SEVERES("Can't homogenize vec in MAT3mult_vec_affine: last coord is 0");
  144.      ret = FALSE;
  145.    }
  146.    else {
  147.       norm_fac = 1.0 / temp[3];
  148.       MAT3_SCALE_VEC(result_vec, temp, norm_fac);
  149.    }
  150.  
  151.    return(ret);
  152. }
  153.  
  154. /* -------------------------------------------------------------------------
  155.  * DESCR   :    Set @result_vec@ to be the cross product of @vec1@ and
  156.  *         @vec2@, in that order.
  157.  *
  158.  * RETURNS :    void
  159.  * ------------------------------------------------------------------------- */
  160. void
  161. MAT3cross_product(
  162.    MAT3vec      result_vec,    /* The computed cross-product (output) */
  163.    register MAT3vec vec1,    /* The first factor (input) */
  164.    register MAT3vec vec2     /* The second factor (input) */
  165.    )
  166. {
  167.    MAT3vec        tempvec;
  168.    register double    *temp = tempvec;
  169.  
  170.    temp[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
  171.    temp[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
  172.    temp[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
  173.  
  174.    MAT3_COPY_VEC(result_vec, temp);
  175. }
  176.  
  177. /* -------------------------------------------------------------------------
  178.  * DESCR :    Computes a unit vector perpendicular to @vec@, and stores it
  179.  *         in @result_vec@. If @is_unit@ is TRUE, @vec@ is assumed to be
  180.  *         of unit length (possibly allowing a time savings by avoiding
  181.  *         normalization of @result_vec@).
  182.  *
  183.  * RETURNS :    void
  184.  *
  185.  * DETAILS :    The method used takes advantage of this technique: As it is
  186.  *         easier to compute a perpendicular vector in R2 than R3, we
  187.  *         essentially do that.  We first determine the component of
  188.  *         @vec@ with the mimimum absolute value, setting corresponding
  189.  *         component of @result_vec@ to 0. We next set the other two
  190.  *         components of @result_vec@ by swapping the remaining
  191.  *         (non-mimimum) components of @vec@ and negating one of these.
  192.  *         Then we normalize as necessary.
  193.  *
  194.  * ------------------------------------------------------------------------- */
  195. #define MAT3ABS(V) ((V) >= 0 ? (V) : (V) * -1)
  196. void
  197. MAT3perp_vec(
  198.    MAT3vec result_vec,        /* The vecotr perp to vec (output) */
  199.    MAT3vec vec,            /* A vector to which a perp is needed (input) */
  200.    int is_unit             /* TRUE is input vector is a unit vector */
  201.    )
  202. {
  203.    double abs_vec[3];
  204.    int min;
  205.    int other1;
  206.    int other2;
  207.    double dot;
  208.  
  209.    /* Compute the absolute value of the components of the input vector. */
  210.  
  211.    abs_vec[0] = MAT3ABS(vec[0]);
  212.    abs_vec[1] = MAT3ABS(vec[1]);
  213.    abs_vec[2] = MAT3ABS(vec[2]);
  214.  
  215.    /* Determine the component with the minimum absolute value, saving its
  216.       index in "min".  Save the indexes of the other two components in
  217.       "other1" and "other2". */
  218.  
  219.    if (abs_vec[0] <= abs_vec[1])
  220.       if (abs_vec[0] <= abs_vec[2]) {
  221.      min = 0; other1 = 1; other2 = 2;
  222.       }
  223.       else {
  224.      min = 2; other1 = 0; other2 = 1;
  225.       }
  226.    else
  227.       if (abs_vec[1] <= abs_vec[2]) {
  228.      min = 1; other1 = 0; other2 = 2;
  229.       }
  230.       else {
  231.      min = 2; other1 = 0; other2 = 1;
  232.       }
  233.  
  234.    /* Generate the perpendicular vector by setting the "min" compenent to
  235.       0, and swapping the "other1" and "other2' components from "vec",
  236.       negating one of these. */
  237.  
  238.    result_vec[min] = 0.0;
  239.    result_vec[other1] = vec[other2];
  240.    result_vec[other2] = -vec[other1];
  241.  
  242.    /* If the input vector has unit length and the component with the mimimum
  243.       absolute value is 0, the computed perpendicular vector already has
  244.       unit length.  Otherwise, we must normalize it. */
  245.  
  246.    if (!is_unit ||
  247.        vec[min] != 0.0)
  248.       MAT3_NORMALIZE_VEC(result_vec, dot);
  249. }
  250.  
  251.  
  252.  
  253.